React is a popular library for creating web apps and mobile apps.
In this article, we’ll look at some tips for writing better React apps.
Pass Props Without Value to Component
We can pass boolean props without a value to a component if its value is true
.
For instance, we can write:
<input type="button" disabled />;
instead of:
<input type="button" disabled={true} />;
They’re the same.
Access Child Component Functions via Refs
We can assign a ref to a component in a class component to access its methods.
For instance, we can write:
class App extends React.Component {
save() {
this.refs.content.getWrappedInstance().save();
}
render() {
return (
<Dialog action={this.save.bind(this)}>
<Content ref="content"/>
</Dialog>);
}
}
class Content extends React.Component {
save() {
//...
}
}
We have the App
component that has the Content
that has a ref assigned to it.
Then we can get the component instance with getWrapperdInstance
.
And we can call the save
method with that.
getDerivedStateFromError and componentDidCatch
Both are methods that let us handle errors in a class component.
getDerivedStateFromError
is a static method that lets us set a state when an error occurs.
componentDidCatch
lets us commit side effects and access this
, which is the component instance.
For instance, we can write:
class ErrorBoundary extends React.Component {
state = { hasError: false };
static getDerivedStateFromError(error) {
return { hasError: true };
}
componentDidCatch(error, info) {
console.log(error, info);
}
render() {
if (this.state.hasError) {
return <h1>error.</h1>;
}
return this.props.children;
}
}
We have the static getDerivedStateFromError
method to access the error
parameter.
Then we can return something which is the state that’s rendered with the next render.
componentDidCatch
lets us access the component instance.
It also has the error
and info
parameters with more error data.
getDerivedStateFromError
works with server-side rendering.
This is because it’s a render phase lifecycle, which is available on server-side rendered apps.
Allow File Input to Select the Same File in React Component
We can let a file input select the same file in a React component if we set it to null
after we click on it.
For instance, we can write:
<input
id="upload"
ref="upload"
type="file"
accept="image/*"
onChange={(event)=> {
this.readFile(event)
}}
onClick={(event)=> {
event.target.value = null
}}
/>
We have the onChange
prop that takes a function to read a file.
In the onClick
prop, we set the file input value to null
.
Passing a Number to a Component
We can pass a number to a component by passing in a number in curly brackets.
For instance, we can write:
Rectangle width={10} height={20} />
Using the Same Component for Different Route path in React Router
We can use the same component for different routes by passing in an array into the path
prop.
So we can write:
<Route exact path={["/add", "/edit"]}>
<User />
</Route>
Conditional Validation in Yup
We can validate a field conditionality with Yup by using the when
method.
For instance, we can write:
validationSchema={yup.object().shape({
showName: yup.boolean(),
name: yup
.string()
.when("showName", {
is: true,
then: yup.string().required("name is required")
})
})
}
We have the showName
boolean field.
And we only validate the name
field when it’s true
as indicated in the is
field.
then
lets us do the validation only when showName
is true
.
Then we return the 'name is required'
message if it is.
Fix ‘ Failed form propType: You provided a checked prop to a form field without an onChange handler.’ Warning
To fix this warning, we can add the checked
prop with a value if we’re creating a controller component.
For instance, we can write:
<input
type="checkbox"
checked={this.props.checked}
onChange={this.onChange}
/>
If it’s an uncontrolled component, we can write populate the defaultChecked
prop:
<input
type="checkbox"
defaultChecked={this.props.checked}
/>
Only Allow Numbers to be Inputted in React
We can set the pattern attribute to the regex string we want for restricting the input to numbers.
For instance, we can write:
<input type="text" pattern="[0-9]*" onInput={this.handleChange.bind(this)} value={this.state.goal} />
We specified the pattern and we listen to the inpurt
pro.
Then in the handleChange
method, we can write:
handleChange(evt) {
const goal = (evt.target.validity.valid) ?
evt.target.value : this.state.goal;
this.setState({ goal });
}
We only set the state if it’s valid, then we won’t get any invalid input in the state.
Conclusion
We can check for input validity in the input handler.
Also, we don’t have to pass in true
explicitly into a prop.
Error boundary components have special hooks that we can run code when errors occur.